package com.mindskip.xzs.utility;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsonschema.JsonSchema;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import static com.fasterxml.jackson.databind.SerializationFeature.WRITE_ENUMS_USING_TO_STRING;


/**
 * @version 3.5.0
 * @description: The type Json util.
 * Copyright (C), 2020-2021, 武汉思维跳跃科技有限公司
 * @date 2021/12/25 9:45
 */
public class JsonUtil {


    public static String pretty(JSONObject object){
//        JSONObject object = JSONObject.parseObject(jsonString);
        String pretty = JSON.toJSONString(object, SerializerFeature.PrettyFormat,
                SerializerFeature.WriteMapNullValue,
                SerializerFeature.WriteDateUseDateFormat);
        return pretty;
    }

    public static String getJSONStringFromJavaBean(Class<? extends Object> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        StringBuffer stb = new StringBuffer("{");
        for (int i = 0; i < fields.length; i++) {
            try {
                Field field = fields[i];
                field.setAccessible(true);
                String name = field.getName();
                stb.append("\"").append(name).
                        append("\"").
                        append(":\"\"").append(",");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        int i = stb.lastIndexOf(",");
        return stb.substring(0,i)+"}";
    }

    public  static  String objectToString(Object object){
        String json = JSONObject.toJSONString(object);
        return json;
    }

    public  static  <T> T stringToObject(String json, Class<T> clazz) {
        if(json == null) {
            return null;
        }
        if(clazz == null) {
            throw new RuntimeException("clazz不能为空");
        }
        try {
            return JSON.parseObject(json, clazz);
        } catch (Exception e) {
            throw new RuntimeException(
                    String.format("JSON字符串转换成对象失败, JSON:[%s], class:[%s]",
                            json, clazz ));
        }
    }

    public static String getJsonSchema(Class clazz) throws IOException {
//        org.codehaus.jackson.map.ObjectMapper mapper = new ObjectMapper();
        ObjectMapper mapper = new ObjectMapper();
        //There are other configuration options you can set.  This is the one I needed.
//        mapper.configure(SerializationConfig.Feature.WRITE_ENUMS_USING_TO_STRING, true);
        mapper.configure(WRITE_ENUMS_USING_TO_STRING, true);

        JsonSchema schema = mapper.generateJsonSchema(clazz);

        return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
    }

    public static void main(String[] args) throws IOException {
//        String jsonSchema = getJsonSchema(PatientInfo.class);
//        System.out.println("jsonSchema");
//        System.out.println(jsonSchema);
//        String jsonStringFromJavaBean = getJSONStringFromJavaBean(NoticeDto.class);
//        System.out.println(jsonStringFromJavaBean);
    }

    public static List<JSONObject> listToPascalCase(List javaObjects){
        List<JSONObject> ret=new ArrayList<>();
        for (Object javaObject : javaObjects) {
            ret.add(toPascalCase(javaObject));
        }
        return ret;
    }

    public static JSONObject toPascalCase(Object javaObject) {
        JSONObject jsonObject = (JSONObject) JSON.toJSON(javaObject);
//        Class<?> aClass = jsonObject.getClass();
//        System.out.println("aClass");
//        System.out.println(aClass);
//        System.out.println("jsonObject");
//        System.out.println(jsonObject);

        JSONObject pascalCase = new JSONObject();
        jsonObject.forEach((key, val) -> {
//            java 第一个字符大写
//            toTitle java
//            to PascalCase
//            StringUtil.ToPascalCase(col.Name)
//            StringUtil
//            StringUtils.Pas
//            pascalCase.put(com.zucc.whatRubbish.util.StrUtil.toPascalCase(key), val);
//            StrUtil.toP
//            com.gm.wj.util.StrUtil
            pascalCase.put(StrUtil.toPascalCase(key), val);
        });

//        System.out.println("pascalCase");
//        System.out.println(pascalCase);
        return pascalCase;
    }


    public static <T> T strToObj(String text, Class<T> clazz) {
        return JSONObject.parseObject(text, clazz);
    }

    //    https://blog.csdn.net/u011008029/article/details/51315339
    public static JSONObject stringToJson(String string){

        string = string.trim();

        if(string.endsWith(",")){
            string=string.substring(0,string.length()-1);
        }

        if(string.startsWith("[")){
            JSONObject jsonObject = JSONArray.parseObject(string);
            JSONArray objects = JSONArray.parseArray(string);
            return jsonObject;
//            return objects;
        }
//        string = string.trim(",");
//        string = string.strip(",");
//        String.st
//        string.stri
//        删掉最后的,

        JSONObject json;
        json = JSONObject.parseObject(string);
//        JSONObject.poa
//        JSONArray.parseObject()
        return json;
    }

    private static final ObjectMapper MAPPER = new ObjectMapper();
    private static final Logger logger = LoggerFactory.getLogger(JsonUtil.class);

    static {
        MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    /**
     * To json str string.
     *
     * @param <T> the type parameter
     * @param o   the o
     * @return the string
     */
    public static <T> String toJsonStr(T o) {
        try {
            return MAPPER.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * To json object t.
     *
     * @param <T>       the type parameter
     * @param json      the json
     * @param valueType the value type
     * @return the t
     */
    public static <T> T toJsonObject(String json, Class<T> valueType) {
        try {
            return MAPPER.<T>readValue(json, valueType);
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }


    /**
     * To json list object list.
     *
     * @param <T>       the type parameter
     * @param json      the json
     * @param valueType the value type
     * @return the list
     */
    public static <T> List<T> toJsonListObject(String json, Class<T> valueType) {
        try {
            JavaType getCollectionType = MAPPER.getTypeFactory().constructParametricType(List.class, valueType);
            List<T> list = MAPPER.readValue(json, getCollectionType);
            return list;
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * To json object t.
     *
     * @param <T>       the type parameter
     * @param stream    the stream
     * @param valueType the value type
     * @return the t
     */
    public static <T> T toJsonObject(InputStream stream, Class<T> valueType) {
        try {
            T object = MAPPER.<T>readValue(stream, valueType);
            return object;
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }
}
